import {Injectable} from '@angular/core';
import {HttpClient, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http';
import {BehaviorSubject, Observable, of} from 'rxjs';
import {Router} from '@angular/router';
import {Token} from './token';
import {catchError} from 'rxjs/operators';
import {environment} from '../../environments/environment';

@Injectable({
  providedIn: 'root'
})
export class TokenService implements HttpInterceptor {

  private clientId = 'client';
  private clientSecret = 'secret';

  constructor(
    private router: Router,
    private http: HttpClient,
    private token: Token
  ) {
  }

  private tokenSubject = new BehaviorSubject('');
  private authSubject = new BehaviorSubject('');

  token$ = this.tokenSubject.asObservable();
  auth$ = this.authSubject.asObservable();

  tokenChangeEvent(token: string) {
    this.tokenSubject.next(token);
  }

  authChangeEvent(auth: any) {
    this.authSubject.next(auth);
  }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    if (req.url.startsWith(environment.oauth + '/oauth/check_token')
      || req.url.startsWith(environment.oauth + '/oauht/token')) {
      return next.handle(req);
    }
    if (this.token && this.token.expire && (this.token.expire - 200000) < new Date().getTime()) {
      // 如果token过期了需要刷新
      this.refresh();
    }
    let clonedReq = req;
    if (this.token && this.token.accessToken) {
      clonedReq = req.clone({
        headers: req.headers.set('Authorization', this.token.tokenType + ' ' + this.token.accessToken)
      });
    }
    return next.handle(clonedReq).pipe(
      catchError(err => {
        if (err['status'] === 403) {
          alert('权限不足');
        }
        return of(err);
      })
    );
  }

  private refresh() {
    this.http.post(environment.oauth + '/oauth/token' +
      '?grant_type=refresh_token&refresh_token=' + this.token.refreshToken, '',
      {
        headers: {'Authorization': this.token.tokenType + ' ' + atob(this.clientId + ':' + this.clientSecret)}
      }).subscribe(res => {
      this.token.setToken(res);
    });
  }

  public getToken(code: string) {
    this.http.post(environment.oauth + '/oauth/token' +
      '?grant_type=authorization_code&redirect_uri=' + encodeURIComponent('http://localhost:4200/login')
      + '&code=' + code, '',
      {headers: {'Authorization': 'Basic ' + btoa(this.clientId + ':' + this.clientSecret)}}).subscribe(res => {
      this.token.setToken(res);
      this.tokenChangeEvent(res['access_token']);
      this.checkAuth();
    });
  }

  public noAuth() {
    return !this.token.accessToken;
  }

  checkToken() {
    // 判断是否有token
    if (this.token && this.token.accessToken) {
      // 如果有则调用事件
      this.tokenChangeEvent(this.token.accessToken);
      this.checkAuth();
    }
  }

  checkAuth() {
    // 判断是否有用户信息
    if (this.token.getAuth()) {
      // 如果有则调用事件
      this.authChangeEvent(this.token.getAuth());
    } else if (this.token.accessToken) {
      // 如果没有则想服务器申请
      this.http.get(environment.oauth + '/oauth/check_token?token=' + this.token.accessToken, {
        headers: {'Authorization': 'Basic ' + btoa(this.clientId + ':' + this.clientSecret)}
      }).subscribe(res => {
        // 获取用户信息后先保存
        this.token.setAuth(res);
        // 之后调用事件
        this.authChangeEvent(res);
      });
    }
  }
}
